import axios from 'axios'
import type { AxiosInstance } from 'axios'
import type {
  RequestInterceptors,
  RequestConfig,
  AxiosRequestConfig2,
  InternalAxiosRequestConfig2,
  AxiosResponse2
} from './type.js'
// HYRequest请求类
class Request {
  instance: AxiosInstance
  interceptors?: RequestInterceptors
  loading?: ReturnType<typeof ElLoading.service> // 通过ReturnType<typeof fn> 可以推断出fn这个函数的返回类型
  constructor(config: RequestConfig) {
    this.instance = axios.create(config)
    this.interceptors = config?.interceptors
    // 请求拦截器
    this.instance.interceptors.request.use(
      this.interceptors?.requestInterceptor,
      this.interceptors?.requestInterceptorCatch
    )
    // 相应拦截器
    this.instance.interceptors.response.use(
      this.interceptors?.responseInterceptor,
      this.interceptors?.responseInterceptorCatch
    )

    // 默认全局请求拦截器
    this.instance.interceptors.request.use(
      (config: InternalAxiosRequestConfig2) => {
        if (config.showLoading !== false) {
          // showLoading被设置为false才关闭loading, 默认loading是开启的
          this.loading = ElLoading.service({
            lock: true,
            text: '正在请求数据',
            background: 'rgba(0, 0, 0, 0.5)'
          })
        }
        return config
      },
      (error) => error
    )
    // 默认全局响应拦截器
    this.instance.interceptors.response.use(
      (res: AxiosResponse2) => {
        // showLoading被设置为false才关闭loading, 默认loading是开启的
        if (res.config?.showLoading !== false) {
          this.loading?.close()
        }
        const data = res.data
        // if (data?.returnCode === '-10001') {
        //   console.log('后端返回信息内容携带自定义状态码， 告诉前端是错误类型的')
        //   console.log('请求失败，错误信息')
        // }
        return data
      },
      (error) => {
        console.log('error', error)
        switch (error.response.status) {
          case 404:
            console.log('访问资源不存在')
            break
        }
        return error
      }
    )
  }

  request<T>(config: AxiosRequestConfig2): Promise<T> {
    return new Promise((resolve, reject) => {
      this.instance
        .request<any, T>(config)
        .then((res) => resolve(res))
        .catch((e) => reject(e))
    })
  }

  get<T>(config: AxiosRequestConfig2): Promise<T> {
    return this.request<T>({ ...config, method: 'GET' })
  }

  post<T>(config: AxiosRequestConfig2): Promise<T> {
    return this.request<T>({ ...config, method: 'POST' })
  }

  delete<T>(config: AxiosRequestConfig2): Promise<T> {
    return this.request<T>({ ...config, method: 'DELETE' })
  }

  patch<T>(config: AxiosRequestConfig2): Promise<T> {
    return this.request<T>({ ...config, method: 'PATCH' })
  }
}

export default Request
